home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Mark Pilgrim / MSG Demo 1.4 / source / Demo ƒ / debinhex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-30  |  5.8 KB  |  257 lines  |  [TEXT/KAHL]

  1. /**********************************************************************\
  2.  
  3. File:        debinhex.c
  4.  
  5. Purpose:    This module handles all the blood and guts of actual
  6.             deBinHexing.
  7.  
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12.  
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with this program in a file named "GNU General Public License".
  20. If not, write to the Free Software Foundation, 675 Mass Ave,
  21. Cambridge, MA 02139, USA.
  22.  
  23. \**********************************************************************/
  24.  
  25. #include "file management.h"
  26. #include "debinhex dispatch.h"
  27. #include "debinhex.h"
  28. #include "util.h"
  29. #include "program globals.h"
  30.  
  31. /* all these globals are internal to debinhex.c */
  32. unsigned char    bstr[64];            /* table of binhex characters with 6-bit index */
  33. unsigned int    crc;                /* binhex checksum */
  34. unsigned char    bufferChar;            /* last char read */
  35. unsigned char    runLenLength;        /* run-len encoding current length */
  36. char            slop;                /* bits we haven't dealt with yet */
  37. int                phase;                /* how many bits we need */
  38.  
  39. Ptr                dbhRaw;                /* raw binhexed data, read in from disk */
  40. unsigned long    dbhSize;            /* actual size of dbhRaw buffer */
  41. unsigned long    dbhPos;                /* where we are in dbhRaw in processing */
  42. unsigned long    dbhTotal;            /* total # of bytes in dbhRaw that contain data */
  43. unsigned char    dbhValues[256];        /* table of values for debinhexing */
  44. Boolean            lookingForRunLen;    /* whether we can handle run-len right now */
  45. Boolean            nowGettingRunLen;    /* whether we are getting a run-len length byte now */
  46.  
  47. enum
  48. {
  49.     no_bits = 0,
  50.     two_bits,
  51.     four_bits,
  52.     six_bits
  53. };
  54.  
  55. int InitDeBinHex(void)
  56. {
  57.     int                i;
  58.     
  59.     Mymemcpy((Ptr)bstr, (Ptr)((long)(*GetString(BINHEX_VALUES_STRING))+1), 64);
  60.     Mymemset((Ptr)dbhValues, 0xff, 256); /* init all values to bad ones */
  61.     for (i=0; i<64; i++)
  62.         dbhValues[bstr[i]]=i; /* put in valid binhex values */
  63.     dbhValues[9]=dbhValues[10]=dbhValues[13]=dbhValues[23]=0x80; /* whitespace */
  64.     
  65.     dbhSize=BINHEX_BUFFER_LENGTH;
  66.     dbhRaw=NewPtr(dbhSize);
  67.     dbhPos=-1L;                    /* need more binhex data from disk */
  68.     lookingForRunLen=FALSE;
  69.     nowGettingRunLen=FALSE;
  70.     phase=no_bits;
  71.     crc=0;
  72.     runLenLength=0x00;
  73. }
  74.  
  75. void EndDeBinHex(void)
  76. {
  77.     DisposePtr(dbhRaw);
  78. }
  79.  
  80. int GetNBytes(int inputRefNum, Ptr outBuf, unsigned long n)
  81. {
  82.     unsigned long    off;
  83.     int                resultCode;
  84.     
  85.     off=0L;
  86.     while (off<n)
  87.     {
  88.         if (dbhPos==-1L)
  89.         {
  90.             dbhTotal=ReadInputFile(inputRefNum, dbhRaw, dbhSize);
  91.             if (dbhTotal<0)
  92.                 return kDiskReadErr;
  93.             dbhPos=0L;
  94.         }
  95.         resultCode=GetByteFromBuffer((unsigned char*)((long)outBuf+off));
  96.         if (resultCode==allsWell)
  97.             off++;
  98.         else if ((resultCode==kBinHexErr) && (off==n-1))
  99.             resultCode=FlushBuffer((unsigned char*)((long)outBuf+(off++)));
  100.         if (resultCode==kBinHexErr)
  101.             return resultCode;
  102.         if (resultCode==kNeedMoreBinHexErr)
  103.             dbhPos=-1L;
  104.     }
  105.     return allsWell;
  106. }
  107.  
  108. int FlushBuffer(unsigned char *outputChar)
  109. {
  110.     *outputChar=bufferChar;
  111.     if (runLenLength!=0x00)
  112.         runLenLength--;
  113.     return allsWell;
  114. }
  115.  
  116. int GetByteFromBuffer(unsigned char *outputChar)
  117. {
  118.     unsigned char        thisByte;
  119.     int                    resultCode;
  120.     
  121.     if (runLenLength!=0x00)
  122.     {
  123.         *outputChar=bufferChar;
  124.         runLenLength--;
  125.         return allsWell;
  126.     }
  127.  
  128.     if (!lookingForRunLen)
  129.     {
  130.         if (!nowGettingRunLen)
  131.         {
  132.             resultCode=ExtractByteFromBinHex(&thisByte);
  133.             if (resultCode!=allsWell)
  134.                 return resultCode;
  135.         }
  136.         else
  137.             thisByte=0x90;
  138.         
  139.         if (thisByte==0x90)
  140.         {
  141.             nowGettingRunLen=TRUE;
  142.             resultCode=ExtractByteFromBinHex(&runLenLength);
  143.             if (resultCode!=allsWell)
  144.                 return resultCode;
  145.             nowGettingRunLen=FALSE;
  146.         }
  147.         bufferChar=thisByte;
  148.         lookingForRunLen=TRUE;
  149.     }
  150.  
  151.     if (!nowGettingRunLen)
  152.     {
  153.         resultCode=ExtractByteFromBinHex(&thisByte);
  154.         if (resultCode!=allsWell)
  155.             return resultCode;
  156.     }
  157.     else
  158.         thisByte=0x90;
  159.     
  160.     if (thisByte==0x90)
  161.     {
  162.         nowGettingRunLen=TRUE;
  163.         resultCode=ExtractByteFromBinHex(&runLenLength);
  164.         if (resultCode!=allsWell)
  165.             return resultCode;
  166.         nowGettingRunLen=FALSE;
  167.         if (runLenLength!=0x00)
  168.         {
  169.             lookingForRunLen=FALSE;
  170.             *outputChar=bufferChar;
  171.             runLenLength--;
  172.             return allsWell;
  173.         }
  174.         else
  175.         {
  176.             *outputChar=bufferChar;
  177.             bufferChar=thisByte;
  178.             return allsWell;
  179.         }
  180.     }
  181.     else
  182.     {
  183.         *outputChar=bufferChar;
  184.         bufferChar=thisByte;
  185.         return allsWell;
  186.     }
  187. }
  188.  
  189. int ExtractByteFromBinHex(unsigned char *outputChar)
  190. {
  191.     unsigned char    thisChar;
  192.     
  193.     while (1)
  194.     {
  195.         if (dbhPos==dbhTotal)
  196.             return kNeedMoreBinHexErr;
  197.         thisChar=dbhValues[*((unsigned char*)((long)dbhRaw+(dbhPos++)))];
  198.         if (thisChar==0xff) /* invalid binhex */
  199.             return kBinHexErr;
  200.         if (thisChar!=0x80) /* only process non-whitespace */
  201.         {
  202.             switch (phase)
  203.             {
  204.                 case no_bits:
  205.                     slop=thisChar&0x3f;
  206.                     phase=two_bits;
  207.                     break;
  208.                 case two_bits:
  209.                     *outputChar=(slop<<2)|(thisChar&0x30)>>4;
  210.                     slop=thisChar&0x0f;
  211.                     phase=four_bits;
  212.                     return allsWell;
  213.                     break;
  214.                 case four_bits:
  215.                     *outputChar=(slop<<4)|(thisChar&0x3c)>>2;
  216.                     slop=thisChar&0x03;
  217.                     phase=six_bits;
  218.                     return allsWell;
  219.                     break;
  220.                 case six_bits:
  221.                     *outputChar=(slop<<6)|(thisChar&0x3f);
  222.                     phase=no_bits;
  223.                     return allsWell;
  224.             }
  225.         }
  226.     }
  227. }
  228.  
  229. int BinHexChecksum(Ptr buffer, unsigned long len, Boolean StartOver)
  230. {
  231.     unsigned long    off;
  232.     
  233.     if (StartOver)
  234.         crc=0;
  235.     
  236.     off=0L;
  237.     while (off<len)
  238.         CalcCRC(&crc, *((unsigned char*)((long)buffer+(off++))));
  239.  
  240.     return crc;
  241. }
  242.  
  243. void CalcCRC(unsigned int *crc, unsigned int v)
  244. {
  245.     int            i;
  246.     Boolean        temp;
  247.     
  248.     for (i=1; i<=8; i++)
  249.     {
  250.         temp=((*crc)&0x8000)!=0;
  251.         *crc=((*crc)<<1)|((v>>7)&0x0001);
  252.         if (temp)
  253.             (*crc)=(*crc)^0x1021;
  254.         v=(v<<1)&0x00ff;
  255.     }
  256. }
  257.